{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Aria2.GID (GID, fromText) where

import Control.Monad (guard)
import Data.Aeson (FromJSON (..), ToJSON (..), withText)
import Data.Coerce (coerce)
import Data.Functor (($>))
import Data.StaticText (Static, create, unwrap)
import Data.Text (Text)
import Data.Text.Encoding.Base64 (isBase64)
import Optics.AffineFold (preview)
import Optics.Prism (Prism', prism')
import Prelude hiding (length)

newtype GID = G (Static Text 16)
  deriving newtype (Eq)
  deriving stock (Show)

instance ToJSON GID where
  toJSON (G gid) = toJSON . unwrap $ gid

instance FromJSON GID where
  parseJSON = withText "GID" go
    where
      go t = case preview fromText t of
        Nothing -> fail ("Not a valid GID: " <> show t)
        Just gid -> pure gid

fromText :: Prism' Text GID
fromText = prism' (unwrap . coerce) go
  where
    go bs = create bs >>= (($>) . guard . isBase64 . unwrap) <*> G
